﻿using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Principal;
using Configuration;

namespace Infrastructure
{
	public class CommunicationPoint
	{
		public static CommunicationPoint Empty
		{
			get
			{
				return new CommunicationPoint
					{
						IP = IPAddress.Loopback.GetAddressBytes(),
						Port = OMConfiguration.Default.DefaultPort,
						Hostname = string.Empty,
						Username = string.Empty
					};
			}
		}

		public static readonly CommunicationPoint Myself = new CommunicationPoint
			{
				IP =
					Dns.GetHostAddresses(string.Empty)
					   .Where(family => family.AddressFamily.Equals(AddressFamily.InterNetwork))
					   .First(ip => !IPAddress.IsLoopback(ip))
					   .GetAddressBytes(),
				Port = OMConfiguration.Default.DefaultPort,
				Hostname = Dns.GetHostName(),
				Username = WindowsIdentity.GetCurrent().User.Translate(typeof(NTAccount)).ToString()
			};

		// IPAddress can't be serialized by Json.NET.
		public byte[] IP
		{
			get;
			set;
		}
		public int Port
		{
			get;
			set;
		}
		public string Hostname
		{
			get;
			private set;
		}
		public string Username
		{
			get;
			private set;
		}

		public override string ToString()
		{
			var s = string.Format("{0}:{1}{4}{2}:{3}", new IPAddress(IP), Port, Hostname, Username, Environment.NewLine);
			return s;
		}

		public override bool Equals(object obj)
		{
			return this.Equals(obj as CommunicationPoint);
		}

		protected bool Equals(CommunicationPoint other)
		{
			if (ReferenceEquals(null, other))
				return false;

			if (ReferenceEquals(this, other))
				return true;

			return (new IPAddress(other.IP).Equals(new IPAddress(IP)))
				   && (other.Port.Equals(Port))
				   && (other.Hostname.Equals(Hostname))
				   && (other.Username.Equals(Username));
		}

		public override int GetHashCode()
		{
			unchecked
			{
				int hashCode = (IP != null ? IP.GetHashCode() : 0);
				hashCode = (hashCode * 397) ^ Port;
				hashCode = (hashCode * 397) ^ (Hostname != null ? Hostname.GetHashCode() : 0);
				hashCode = (hashCode * 397) ^ (Username != null ? Username.GetHashCode() : 0);
				return hashCode;
			}
		}
	}
}